/**
 * This is about <code>Cookie.java</code>.
 * @author illmare
 * @date 2009. 9. 16.
 * @description
 *
 *
 */

package com.crowdgeeks.common.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.Key;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


/**
 * Cotweet Cookie 순서
 * 
 * UserID --> idx : 0 
 * UserName 
 * Position 
 * Extension 
 * Mobile --> idx : 4 
 * LandLine
 * Email DeptName 
 * DeptID --> idx : 8
 * 
 * @author illmare
 * 
 */

public class CookieUtil {

	/**
	 * Exception 을 어떻게 처리할까 고민하다가.. 그냥 둠.
	 * 
	 * @param response
	 * @param name
	 * @param value
	 */
	public void setCookieValue(HttpServletResponse response, String name, String value) {

		if(name != null && value != null) {
			String cookieEncValue = null;
			try {
				cookieEncValue = URLEncoder.encode(value, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			Cookie cookie = new Cookie(name, cookieEncValue);
			cookie.setDomain(".xener.com");
			cookie.setPath("/");
			cookie.setMaxAge(60 * 15); // 쿠키 유지 시간 15분

			response.addCookie(cookie);
		}
	}

	/**
	 * 사용자 정보를 기반으로 쿠키를 생성한다. 쿠키명은 cotweet이며, domain은 xener.com, path는 '/'를 기준으로
	 * 함 초기 유지시간으로 15분으로 제한하였으나, 전화기능의 문제로 -1(영구) 값으로 변경.
	 * 
	 * 쿠키값은 & 값을 연결자로 하나의 문자열로 구성하였고 URLEncoder를 사용하여 Encryption 함
	 * 
	 * @param response
	 * @param member
	 */
//	public void createCookie(HttpServletResponse response, MemberVO member) {
//
//		if(member != null) {
//
//			String value = null;
//			Cookie cookie = null;
//
//			try {
//				StringBuffer _cookieValueStr = new StringBuffer();
//
//				_cookieValueStr.append(member.getUserID()).append("&").append(member.getUserName()).append("&").append(member.getPosition()).append("&").append(member.getExtension()).append("&").append(member.getMobile()).append("&").append(member.getLandline()).append("&").append(member.getEmail()).append("&").append(((DeptVO) member.getDept()).getDeptName()).append("&").append(((DeptVO) member.getDept()).getDeptID()).append("&").append(member.getImageUrl());
//
//				value = _cookieValueStr.toString();
//				value = URLEncoder.encode(value, "UTF-8"); // URL Encoding
//				// value = sourceEncode(value, member.getUserId());
//
//				cookie = new Cookie("cotweet", value);
//				cookie.setMaxAge(-1);
//				cookie.setDomain("xener.com");
//				cookie.setPath("/");
//				response.addCookie(cookie);
//
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}
//	}

	/**
	 * 쿠키값을 해석하는 메소드, idx 값을 클래스 상단의 idx 리스트 참조
	 * 
	 * @param request
	 * @param idx
	 * @return
	 */
	public String getCookieValue(HttpServletRequest request, int idx) {

		List<String> cookieList = getCotweetCookie(request);

		if(idx >= cookieList.size())
			return "";
		else
			return cookieList.get(idx);
	}

	/**
	 * HttpServketRequest 에 포함된 모든 쿠키중에서 cotweet 이름의 쿠키만을 찾아내서 list 형태로 변경함
	 * Decryption 은 단순 URLDecoder 를 이용함
	 * 
	 * @param request
	 * @return
	 */
	public List<String> getCotweetCookie(HttpServletRequest request) {

		Cookie[] cookies = request.getCookies();
		List<String> list = new ArrayList<String>();

		if(cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				
				System.out.println("*** cookies[ " + i + " ].getName() : " + cookies[i].getName());
				if (cookies[i].getName().equals("code")) {
					try {
						list = stringToListForCookie(URLDecoder.decode(cookies[i].getValue(), "UTF-8"));
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
				}
			}
		}

		return list;
	}

	/**
	 * & 로 연결된 id 문자열을 list로 변경
	 * @param id
	 * @return
	 */
	public List<String> stringToListForCookie(String str) {
		List<String> list = new ArrayList<String>();
		String[] idList = str.split("&");

		list = Arrays.asList(idList);

		// for(int i=0; i < idList.length; i++)
		// list.add(idList[i]);

		return list;
	}

	/**
	 * cotweet 쿠키를 삭제.. 쿠키 자체를 삭제하는 것이 아니라 cotweet 의 이름으로 된 쿠키의 설정된 값들을 초기화 시킴
	 * 
	 * @param request
	 * @param response
	 */
	public void deleteCookie(HttpServletRequest request, HttpServletResponse response) {

		if(request.getCookies() != null) {
			Cookie cookie = new Cookie("cotweet", "");
			cookie.setValue("");
			cookie.setMaxAge(0);
			cookie.setDomain("xener.com");
			cookie.setPath("/");

			response.addCookie(cookie);
		}

	}

	/**
	 * 보안을 강화가 필요한 경우는 단순하게 URLEncoder 만으로 문자열을 encryption 하는 것은 위험함. 따라서 몇가지 보안
	 * 알고리즘과 public key를 이용하여 사용자에게 전달할 key를 생성하는 메소드
	 * 
	 * @param algorithm
	 * @param publicKeyStr
	 * @return
	 * @throws Exception
	 */
	public Key createKey(String algorithm, String publicKeyStr) throws Exception {

		Key key = null;

		try {
			BASE64Decoder decoder = new BASE64Decoder();
			KeyGenerator keygenerator = KeyGenerator.getInstance(algorithm);
			byte[] decodedStr = decoder.decodeBuffer(publicKeyStr);
			SecureRandom secureRandom = new SecureRandom();
			secureRandom.setSeed(decodedStr);
			keygenerator.init(secureRandom);
			key = keygenerator.generateKey();
		} catch (Exception e) {
			System.out.println("key generate error " + e);
		}
		return key;
	}

	/**
	 * 지정된 guid 를 이요하여 문자열을 encoding 하는 메소드
	 * 
	 * @param source
	 * @param guid
	 * @return
	 * @throws Exception
	 */
	public String sourceEncode(String source, String guid) throws Exception {

		String decodeCode = "";

		StringBuffer returnCode = new StringBuffer();
		// String returnCode = "";

		try {
			Cipher cipher = null;
			BASE64Encoder encoder = null;
			byte[] secSource = null;
			byte[] sourceByte = null;
			cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
			// cipher.init(Cipher.ENCRYPT_MODE, getKey(date_key));
			cipher.init(Cipher.ENCRYPT_MODE, createKey("DES", guid));
			sourceByte = source.getBytes("UTF8");
			secSource = cipher.doFinal(sourceByte);
			encoder = new BASE64Encoder();
			decodeCode = encoder.encode(secSource);
			int secsize = 78;
			int startidx = 0;
			int endidx = 0;

			for (int i = 0; i <= decodeCode.length() / secsize; i++) {
				if(i == 0)
					startidx = 0;
				else
					startidx = i * secsize;

				endidx = (i + 1) * secsize - 2;

				if(endidx > decodeCode.length())
					endidx = decodeCode.length();

				returnCode.append(decodeCode.substring(startidx, endidx));
				// returnCode += decodeCode.substring(startidx, endidx);
			}
		} catch (Exception e) {
			System.out.println("Error sourceEncode():" + e);
			e.printStackTrace();
		}
		return returnCode.toString();
	}

	/**
	 * 지정된 guid를 이요하여 주어진 문자열을 decoding 하는 메소드
	 * 
	 * @param source
	 * @param guid
	 * @return
	 * @throws Exception
	 */
	public String sourceDecode(String source, String guid) throws Exception {

		String returnCode = "";
		try {
			Cipher cipher = null;
			BASE64Decoder decoder = null;
			byte[] sourceByte = null;
			byte[] decodeSource = null;

			cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
			// cipher.init(Cipher.DECRYPT_MODE, getKey(date_key));
			cipher.init(Cipher.DECRYPT_MODE, createKey("DES", guid));
			decoder = new BASE64Decoder();
			sourceByte = decoder.decodeBuffer(source);
			decodeSource = cipher.doFinal(sourceByte);
			returnCode = new String(decodeSource, "UTF8");
		} catch (Exception e) {
			System.out.println("Error sourceDecode():" + e);
			System.out.println("source is : " + source);
		}
		return returnCode;
	}

	/**
	 * 유저의 쿠키를 확인해 로그인 여부 확인
	 * 
	 * @param request
	 * @param user_id
	 * @return
	 */
	public boolean checkLogin(HttpServletRequest request, String user_id) {

		if(user_id == null || user_id.equals(""))
			return false;

		if(getCookieValue(request, 0).equals(user_id))
			return true;
		else
			return false;
	}

	/**
	 * 사용자 ID 를 확인해 ID가 있으면 로그인 상태로 판단
	 * 
	 * @param request
	 * @return
	 */
	public boolean simpleCookieCheck(HttpServletRequest request) {

		if(getCookieValue(request, 0).length() > 1)
			return true;
		else
			return false;
	}
}
